﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using GenericLibrary.Common;



namespace GenericLibrary.Modeling.DynamicAgent {


    ////定义动态系统模型，对于多系统交互的应用，由系统自身定义和维护交互的拓扑结构
    ////注意：该接口没有定义系统的输入，完全由实现类定义。在概念上，任何对该系统对象的写入操作都作为系统的输入对待，而且任何写入操作都是发生在“当前时刻”，这是由仿真框架确保的。
    ////这个接口不定义具体的交互形式，即没有具体的输入输出格式，这样，一方面提供充分的灵活性，另一方面亦是不得已而为之：如果规定了输入输出，则必须在系统外定义系统交互的拓扑结构，这就违背了“由系统自身维护交互的拓扑结构的原则”
    //public interface IDynamicSystem {

    //    bool HasInputs { get; }
    //    void Evolve( double timeStep );//更新系统的内部状态到timeStep时间步长后,timeStep > 0 这是由时间驱动的系统状态变化
    //    void ResolveInputs();//这是由外部输入驱动的系统状态变化，，用于同步外部输入，接受外部输入，将外部输入同步更新到系统的内部状态上（避免异步更新外部输入，如有A和B同时写入本对象，只有当A和B都执行完各自对本对象的Output之后再执行本对象的AcceptChanges方法可实现同步更新），仿真框架在执行完当前时刻所有系统的输出之后，会统一调用所有的这一方法，以将输出同步应用到各个系统的状态更新上去
    //    void Output();//定义系统的输出，在多系统交互的应用中，具体的输出行为可取决于系统自身维护的拓扑结构
    //    double OutputDelay { get; }//定义系统产生输出相对当前时刻的延迟时间，该值可以取决于系统内部状态
    //}

    //public class DynamicAgentCollection : ICollection<DynamicAgent> {

    //    private List<DynamicAgent> _agents;

    //    public bool Evolve() {
    //        try {
    //            int i = 0;
    //            for( int j = 1; j < this._agents.Count; j++ ) {
    //                int compareResult = this._agents[ i ].OutputDelay.CompareTo( this._agents[ j ].OutputDelay );
    //                if( compareResult < 0 ) {
    //                    continue;
    //                } else if( compareResult > 0 ) {
    //                    i = 0;
    //                } else {
    //                    i++;
    //                }
    //                DynamicAgent agent = this._agents[ i ];
    //                this._agents[ i ] = this._agents[ j ];
    //                this._agents[ j ] = agent;
    //            }

    //            double timeStep = this._agents[ 0 ].OutputDelay;
    //            if( double.IsNaN( timeStep ) || timeStep < 0 ) {
    //                throw new Exception();
    //            } else if( double.IsPositiveInfinity( timeStep ) ) {
    //                return false;
    //            } else {
    //                if( timeStep > 0 ) {
    //                    foreach( DynamicAgent agent in this._agents ) {
    //                        agent.Synchronize( timeStep );
    //                    }
    //                }
    //                for( ; i >= 0; i-- ) {
    //                    this._agents[ i ].Output();
    //                }
    //                return true;
    //            }
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public DynamicAgentCollection() {

    //        this._agents = new List<DynamicAgent>();
    //    }

    //    #region ICollection<DynamicAgent> Members

    //    public void Add( DynamicAgent item ) {
    //        try {
    //            if( item._collection != null && item._collection != this ) {
    //                item._collection.Remove( item );
    //                this._agents.Add( item );
    //                item._collection = this;
    //            }
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public void Clear() {
    //        try {
    //            foreach( DynamicAgent agent in this._agents ) {
    //                agent._collection = null;
    //            }
    //            this._agents.Clear();
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public bool Contains( DynamicAgent item ) {
    //        try {
    //            return item._collection == this;
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public void CopyTo( DynamicAgent[] array, int arrayIndex ) {
    //        try {
    //            this._agents.CopyTo( array, arrayIndex );
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public int Count {
    //        get {
    //            return this._agents.Count;
    //        }
    //    }

    //    public bool IsReadOnly {
    //        get {
    //            try {
    //                return ( this._agents as ICollection<DynamicAgent> ).IsReadOnly;
    //            } catch( Exception ) {
    //                Debug.Assert( false );
    //                throw;
    //            }
    //        }
    //    }

    //    public bool Remove( DynamicAgent item ) {
    //        try {
    //            if( item._collection == this ) {
    //                item._collection = null;
    //                return this._agents.Remove( item );
    //            }
    //            return false;
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    #endregion

    //    #region IEnumerable<DynamicAgent> Members

    //    public IEnumerator<DynamicAgent> GetEnumerator() {
    //        try {
    //            return ( this._agents as IEnumerable<DynamicAgent> ).GetEnumerator();
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    #endregion

    //    #region IEnumerable Members

    //    IEnumerator IEnumerable.GetEnumerator() {
    //        try {
    //            return ( this._agents as IEnumerable ).GetEnumerator();
    //        } catch( Exception ) {
    //            Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    #endregion
    //}


    //public abstract class DynamicAgent {

    //    internal DynamicAgentCollection _collection;

    //    public ICollection<DynamicAgent> Collection {
    //        get {
    //            return this._collection;
    //        }
    //    }

    //    public bool IsDetached {
    //        get {
    //            return this._collection == null;
    //        }
    //    }

    //    internal protected abstract void Synchronize( double timeStep );
    //    internal protected abstract void Output();
    //    internal protected abstract double OutputDelay { get; }

    //}

    public interface IDynamicAgent {

        void Synchronize( double timeStep );

        /// <summary>
        ///输出方法，是否应允许对所处集合进行改动？
        ///不能允许作为集合成员的个体对集合进行改动，即每个成员的取舍只能在整个集合遍历结束后作出，在遍历期间对集合进行修改是非法的！
        /// </summary>
        /// <param name="collection"></param>
        void Output( IEnumerable<IDynamicAgent> collection );

        /// <summary>
        /// Set the proterty with positive value to schedule a pending output(pending output invokes synchronize in advance)
        /// set with 0 to schedule an immediate output(Immediate output do not invoke synchronize in advance)
        /// set with negative value to remove the subject agent from the collection and quit from the evolution iteration.
        /// </summary>
        double OutputDelay { get; }

    }

    public class DynamicAgentCollection : ICollection<IDynamicAgent> {

        private List<IDynamicAgent> _agents;

        public DynamicAgentCollection() {
            this._agents = new List<IDynamicAgent>();
        }

        public bool Evolve() {
            try {
                int i = 0;
                for( int j = 1; j < this._agents.Count; j++ ) {
                    int compareResult = this._agents[ i ].OutputDelay.CompareTo( this._agents[ j ].OutputDelay );
                    if( compareResult < 0 ) {
                        continue;
                    } else if( compareResult > 0 ) {
                        i = 0;
                    } else {
                        i++;
                    }
                    IDynamicAgent agent = this._agents[ i ];
                    this._agents[ i ] = this._agents[ j ];
                    this._agents[ j ] = agent;
                }

                double timeStep = this._agents[ 0 ].OutputDelay;
                if( double.IsNaN( timeStep ) || timeStep < 0 ) {
                    throw new Exception();
                } else if( double.IsPositiveInfinity( timeStep ) ) {
                    return false;
                } else {
                    if( timeStep > 0 ) {
                        foreach( IDynamicAgent agent in this._agents ) {
                            agent.Synchronize( timeStep );
                        }
                    }
                    for( ; i >= 0; i-- ) {
                        this._agents[ i ].Output( this._agents.AsReadOnly() );
                    }
                    return true;
                }
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }



        #region ICollection<IDynamicAgent> Members

        public void Add( IDynamicAgent item ) {
            try {
                if( !this._agents.Contains( item ) ) {
                    this._agents.Add( item );
                }
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        public void Clear() {
            try {
                this._agents.Clear();
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        public bool Contains( IDynamicAgent item ) {
            try {
                return this._agents.Contains( item );
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        public void CopyTo( IDynamicAgent[] array, int arrayIndex ) {
            try {
                this._agents.CopyTo( array, arrayIndex );
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        public int Count {
            get {
                try {
                    return this._agents.Count;
                } catch( Exception ) {
                    System.Diagnostics.Debug.Assert( false );
                    throw;
                }
            }
        }

        public bool IsReadOnly {
            get {
                try {
                    return ( this._agents as ICollection<IDynamicAgent> ).IsReadOnly;
                } catch( Exception ) {
                    System.Diagnostics.Debug.Assert( false );
                    throw;
                }
            }
        }

        public bool Remove( IDynamicAgent item ) {
            try {
                return this._agents.Remove( item );
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        #endregion

        #region IEnumerable<IDynamicAgent> Members

        public IEnumerator<IDynamicAgent> GetEnumerator() {
            try {
                return ( this._agents as IEnumerable<IDynamicAgent> ).GetEnumerator();
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator() {
            try {
                return ( this._agents as IEnumerable ).GetEnumerator();
            } catch( Exception ) {
                System.Diagnostics.Debug.Assert( false );
                throw;
            }
        }

        #endregion
    }

    //public class DynamicAgentEvolver {

    //    private List<WeakReference> _outputList;
    //    private int _outputCount;

    //    public DynamicAgentEvolver() {
    //        this._outputList = new List<WeakReference>();
    //        this._outputCount = 0;
    //    }

    //    public int BufferSize {
    //        get {
    //            try {
    //                return this._outputList.Count;
    //            } catch( Exception ) {
    //                System.Diagnostics.Debug.Assert( false );
    //                throw;
    //            }
    //        }
    //    }

    //    public void Purge() {
    //        try {
    //            this._outputList.Clear();
    //        } catch( Exception ) {
    //            System.Diagnostics.Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    private void Enqueue( IDynamicAgent agent ) {
    //        try {
    //            if( this._outputCount > 0 ) {
    //                double timeStep = this._outputList[ 0 ].OutputDelay, outputDelay = agent.OutputDelay;
    //                if( outputDelay > timeStep ) {
    //                    return;
    //                } else if( outputDelay < timeStep ) {
    //                    this._outputCount = 0;
    //                }
    //            }
    //            if( this._outputList.Count > this._outputCount ) {
    //                this._outputList[ this._outputCount ] = agent;
    //            } else {
    //                this._outputList.Add( agent );
    //            }
    //            this._outputCount++;
    //        } catch( Exception ) {
    //            System.Diagnostics.Debug.Assert( false );
    //            throw;
    //        }
    //    }

    //    public bool Evolve( IEnumerable<IDynamicAgent> population ) {
    //        try {
    //            foreach( IDynamicAgent agent in population ) {
    //                this.Enqueue( agent );
    //            }
    //            if( this._outputCount > 0 ) {
    //                double timeStep = (this._outputList[ 0 ].Target as IDynamicAgent).OutputDelay;
    //                foreach( IDynamicAgent agent in population ) {
    //                    agent.Synchronize( timeStep );
    //                }
    //                for( int i = 0; i < this._outputList.Count; i++ ) {
    //                    if( i < this._outputCount ) {
    //                        (this._outputList[ i ].Target as IDynamicAgent).Output( population );
    //                    }
                        
    //                }
    //                this._outputCount = 0;
    //                return true;
    //            }
    //            return false;
    //        } catch( Exception ) {
    //            System.Diagnostics.Debug.Assert( false );
    //            throw;
    //        }
    //    }




    //}
}
